package com.book.modules.helper;

import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.book.common.api.entity.CurrentUser;
import com.book.common.api.oauth.CacheKey;
import com.book.common.api.oauth.HystrixConstant;
import com.book.common.helper.I18nHelper;
import com.book.common.result.Failed;
import com.book.common.result.RestResponse;
import com.book.common.result.Success;
import com.book.common.util.GuavaCacheUtil;
import com.book.modules.util.HttpContextUtil;
import com.book.oauth.server.role.vo.RoleVo;
import com.book.oauth.server.user.hystrix.IOauthHystrix;
import com.book.oauth.server.user.vo.CurrentUserDetail;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Map;

/**
 * Description： 用户帮助类
 *
 * @Author： leo.xiong
 * @CreateDate： 2019/10/10 15:04
 * @Email： leo.xiong@suyun360.com
 * Version：1.0
 */
@Slf4j
@Component
public class CurrentUserHelper {

    public static final String ACCESS_TOKEN = "access_token";

    @Value("${custom.clientId:}")
    protected String clientId;

    @Value("${custom.clientSecret:}")
    protected String clientSecret;

    @Value("${custom.scope:}")
    protected String scope;

    @Autowired(required = false)
    private IOauthHystrix oauthHystrix;

    @Autowired
    private I18nHelper i18nHelper;

    /**
     * 获取token信息
     * 不存在token则生产一个
     *
     * @param userName
     * @param passWord
     * @param grantType
     * @return
     */
    public Map<String, String> getOauthToken(String userName, String passWord, String grantType) {
        Map tokenMap = null;
        try {
            String token = getRequestToken();
            if (StringUtils.isNotEmpty(token)) {
                tokenMap = GuavaCacheUtil.get(CacheKey.PUBLIC_LOGIN_NAME + token, Map.class);
                if (tokenMap != null) {
                    return tokenMap;
                }
            }
            tokenMap = oauthHystrix.getOauthToken(userName, passWord, clientId, clientSecret, grantType, scope);
            if (tokenMap == null) {
                if (StringUtils.isNotEmpty(passWord)) {
                    throw new RuntimeException(i18nHelper.get("BOOK:CORE:10010"));
                } else {
                    throw new RuntimeException("BOOK:CORE:10008");
                }
            }
            tokenMap.remove("scope");
            tokenMap.remove("grant_type");
            tokenMap.remove("jti");
            GuavaCacheUtil.put(CacheKey.PUBLIC_LOGIN_NAME + tokenMap.get(ACCESS_TOKEN), tokenMap);
        } catch (Exception e) {
            log.error("获取token异常", e);
        }
        return tokenMap;
    }

    /**
     * 根据token获取当前登录用户信息
     *
     * @param token
     * @return
     */
    public RestResponse<CurrentUser> getUserByToken(String token) throws RuntimeException {
        if (StringUtils.isEmpty(token)) {
            return new Failed("BOOK:CORE:10000", i18nHelper.get("BOOK:CORE:10000"));
        }
        try {
            CurrentUser currentUser = GuavaCacheUtil.get(CacheKey.PUBLIC_USER_TOKEN + token, CurrentUser.class);
            if (currentUser != null) {
                return new Success<>(currentUser);
            }
            RestResponse<CurrentUser> restResponse = oauthHystrix.getPrincipal(token);
            if (restResponse == null || restResponse.isFailed() || restResponse.getData() == null) {
                return new Failed(restResponse.getErrorCode(), restResponse.getErrorMsg());
            }
            restResponse.getData().setToken(token);
            GuavaCacheUtil.put(CacheKey.PUBLIC_USER_TOKEN + token, restResponse.getData());
            return restResponse;
        } catch (Exception e) {
            log.error("路由异常", e);
            return new Failed("BOOK:COMMON:10037", i18nHelper.get("BOOK:COMMON:10037", "oauth-server") + e.getMessage());
        }
    }

    /**
     * 获取用户详情信息
     *
     * @param currentUser
     * @return
     */
    public CurrentUserDetail getCurrentUserDetail(CurrentUser currentUser) {
        if (currentUser == null || StringUtils.isEmpty(currentUser.getId())) {
            log.warn("查询用户传入的参数有误:{}", currentUser);
            return null;
        }
        CurrentUserDetail currentUserDetail = GuavaCacheUtil.get(CacheKey.PUBLIC_USER_ID + currentUser.getId(), CurrentUserDetail.class);
        if (currentUserDetail != null) {
            return currentUserDetail;
        }
        RestResponse<CurrentUserDetail> restResponse = oauthHystrix.getCurrentUserDetail(currentUser);
        if (restResponse == null || restResponse.isFailed() || restResponse.getData() == null) {
            log.warn("查询用户信息详情失败:{}", restResponse);
            return null;
        }
        GuavaCacheUtil.put(CacheKey.PUBLIC_USER_ID + currentUser.getId(), restResponse.getData());
        return restResponse.getData();
    }

    /**
     * 清除token信息
     */
    public RestResponse logout() {
        try {
            String token = getRequestToken();
            if (token != null) {
                RestResponse<String> response = oauthHystrix.logout(token);
                GuavaCacheUtil.remove(CacheKey.PUBLIC_USER_TOKEN + token);
                GuavaCacheUtil.remove(CacheKey.PUBLIC_LOGIN_NAME + token);
                if (response != null && response.isSuccess()) {
                    return new Success("", i18nHelper.get("BOOK:CORE:10001"));
                } else {
                    return new Failed("BOOK:CORE:10001", i18nHelper.get(response != null ? response.getErrorMsg() : "BOOK:CORE:10001"));
                }
            } else {
                return new Failed("BOOK:CORE:10000", i18nHelper.get("BOOK:CORE:10000"));
            }
        } catch (Exception e) {
            log.error("移除token异常", e);
            return new Failed("BOOK:CORE:10001", i18nHelper.get("BOOK:CORE:10001") + e.getMessage());
        }
    }

    /**
     * 获取当前线程的reques信息
     *
     * @return
     */
    public String getRequestToken() {
        return getRequestToken(HttpContextUtil.getHttpServletRequest());
    }

    /**
     * 获取token信息，如果header中存在，取header，否则取cookies如果cookies不存在，则返回空
     *
     * @param request
     * @return
     */
    public String getRequestToken(HttpServletRequest request) {
        String bearAccessToken = request.getHeader(HystrixConstant.AUTHORIZATION);
        if (StringUtils.isNotEmpty(bearAccessToken)) {
            bearAccessToken = bearAccessToken.trim().replace(HystrixConstant.BEARER, "").trim();
            return bearAccessToken;
        }
        Cookie[] cookies = request.getCookies();
        if (cookies == null) {
            return null;
        }
        for (Cookie cookie : cookies) {
            if (HystrixConstant.AUTHORIZATION.equals(cookie.getName())) {
                return cookie.getValue();
            }
        }
        return null;
    }

    /**
     * 获取当前登录用户信息
     *
     * @return
     */
    public CurrentUser getCurrentUser() {
        RestResponse<CurrentUser> restResponse = getUserByToken(getRequestToken());
        if (restResponse != null && restResponse.isSuccess()) {
            return restResponse.getData();
        }
        return null;
    }

    /**
     * 根据request获取当前用户信息
     *
     * @param request
     * @return
     */
    public CurrentUser getCurrentUser(HttpServletRequest request) {
        String token = getRequestToken(request);
        if (StringUtils.isEmpty(token)) {
            return null;
        }
        RestResponse<CurrentUser> restResponse = getUserByToken(token);
        if (restResponse == null || restResponse.isFailed() || restResponse.getData() == null) {
            log.warn("获取用户信息失败,token:{}", token);
            return null;
        }
        return restResponse.getData();
    }

    /**
     * 创建一个普通用户，可用于第三方接口等
     *
     * @param userId
     * @param userName
     * @param thirdPath
     * @return
     */
    public CurrentUserDetail buildCommonCurrentUserDetail(String userId, String userName, String thirdPath) {
        RoleVo roleVo = new RoleVo();
        roleVo.setRoleName("thirdPathRole");
        return buildCommonCurrentUserDetail(userId, userName, thirdPath, roleVo, null);
    }

    public CurrentUserDetail buildCommonCurrentUserDetail(String userId, String userName, String thirdPath, RoleVo roleVo) {
        return buildCommonCurrentUserDetail(userId, userName, thirdPath, roleVo, null);
    }

    public CurrentUserDetail buildCommonCurrentUserDetail(String userId, String userName, String thirdPath, RoleVo roleVo, List<String> permissionList) {
        CurrentUserDetail currentUserDetail = new CurrentUserDetail();
        currentUserDetail.setId(userId);
        currentUserDetail.setUsername(thirdPath + StringPool.DASH + userName);
        currentUserDetail.setRoleName(roleVo.getRoleName());
        currentUserDetail.setRoleId(roleVo.getId());
        currentUserDetail.setPermissionList(permissionList);
        String token = thirdPath + StringPool.DASH + userId;
        GuavaCacheUtil.put(CacheKey.PUBLIC_USER_TOKEN + token, currentUserDetail);
        return currentUserDetail;
    }
}
